import { Ref, SetupContext, computed, inject, onUnmounted, ref, toRefs, watch } from 'vue';
import { UploaderProps } from '../uploader.props';
import { FUploadFileExtend, FUploadPreviewColumn, TGetService, TNotifyService, UploadFile, UploadInput, UploadOutput } from './type';
import {
    sortPreviewData,
    judgeContentTypeLimit,
    judegeFileSizeLimit,
    formatUploadOpts,
    canEditFile,
    getFileTypeClassName,
    getUploadProgress,
    getRealFileSize,
    changeUploadFileToFileExtend
} from '../composition/utils';
import { FFileUploaderService } from '../service/uploader-service';
import { Observable, Subject, Subscription, BehaviorSubject } from "rxjs";

export const useUploader = (props: UploaderProps, ctx: SetupContext, getSer: TGetService): any => {

    let notifySer = getSer.getNotifyService();
    let apiSer = getSer.getAPIService();
    const {
        uploadedCount,
        disabled,
        uploadVisible,
        uploadDisabled,
        uploadSelectText,
        previewVisible,
        customInfo,
        uploadOptions,
        fileInfos,
        orderField,
        previewEnableMulti,
        noDownload,
        previewReadonly,
        previewColumns,
        uploadEnableMulti,
        editfile,
        noPreview,
        extendConfig
    } = toRefs(props);

    // 全选状态
    const previewSelectAllBtnChecked = ref(false);
    // 记录选中数据
    const previewMultiSelected: Ref<Array<FUploadFileExtend>> = ref([]);
    // 用于模版的展示
    const previewMultiSelectedLength = computed(() => {
        return previewMultiSelected.value.length;
    });
    // 记录配置
    const uploadInputOpts: any = ref({
        // 允许上传的文件类型
        allowedContentTypes: '*',
        // 默认不限制附件上传个数
        maxUploads: 0,
        // 单位KB，默认是12M
        maxFileSize: '12MB'
    });
    // 记录文件个数
    const uploadFiles: Ref<Array<UploadOutput>> = ref([]);
    const innerUploadOptions = ref();
    // 记录上传事件
    let uploadInputEvent: Subject<UploadInput> = new Subject();
    // 在服务中处理上传事件
    apiSer.initInputEvents(uploadInputEvent);
    // 变更
    apiSer.getEvents().subscribe((event: UploadOutput) => {
        debugger;
        uploadOutputHandler(event);
    });

    /**
     * 额外的配置
     */
    watch(extendConfig,()=>{
        apiSer.setExtendServerConfig(extendConfig.value);
    });
    /**
     * 监测上传配置改变
     */
    watch(uploadOptions, (status) => {
        uploadInputOpts.value = formatUploadOpts(uploadOptions.value, uploadInputOpts.value);
        apiSer.setOptions(uploadInputOpts.value);
    });

    // 格式化数据
    const innerFileInfos = computed(() => {
        // 处理其他数据切换引起数据源的变更
        if (!fileInfos.value.length || previewMultiSelected.value.length !== fileInfos.value.length) {
            previewSelectAllBtnChecked.value = false;
        }
        let formatValue = fileInfos.value.map((item: FUploadFileExtend) => {
            if (!item.hasOwnProperty('size')) {
                item['size'] = undefined;
            }
            if (!item.hasOwnProperty('createTime')) {
                item['createTime'] = undefined;
            }
            return item;
        });

        formatValue.sort(sortPreviewData(orderField.value));

        if (previewEnableMulti.value) {
            let newFormatValue = formatValue.map((item: FUploadFileExtend) => {
                item['checked'] = !!previewMultiSelected.value.find((n) => n.id === item.id) || previewSelectAllBtnChecked.value;
                return item;
            });
            previewMultiSelected.value = [...newFormatValue].filter((n) => n.checked);
            // 返回格式化数据
            return newFormatValue;
        } else {
            return formatValue;
        }
        //_renameFromDialog = "";
    });

    /**
     * 提示结构
     * @returns
     */
    function beforeUploadSupportInfoHtml() {
        return (
            <div class="ffileupload--support-info">
                <ul class="support-info--wrapper">
                    {customInfo.value ? (
                        <li>
                            <span class="support-info--item-detail" v-html={customInfo.value}></span>
                        </li>
                    ) : (
                        <>
                            {judgeContentTypeLimit(uploadInputOpts.value['allowedContentTypes']) ? (
                                <li>
                                    <span>支持类型：</span>
                                    <span class="support-info--item-detail">
                                        {uploadInputOpts.value['allowedContentTypes']}, &nbsp;&nbsp;
                                    </span>
                                </li>
                            ) : (
                                ''
                            )}
                            {judegeFileSizeLimit(uploadInputOpts.value['maxFileSize']) ? (
                                <li>
                                    <span>单个文件限制：</span>
                                    <span class="support-info--item-detail">{uploadInputOpts.value['maxFileSize']}, &nbsp;&nbsp;</span>
                                </li>
                            ) : (
                                ''
                            )}
                            {uploadInputOpts.value['maxUploads'] > 0 ? (
                                <li>
                                    <span>文件总数限制：</span>
                                    <span class="support-info--item-detail">{uploadInputOpts.value['maxUploads']}个</span>
                                </li>
                            ) : (
                                ''
                            )}
                        </>
                    )}
                </ul>
            </div>
        );
    }
    /**
     * 返回上传附件的名称模版
     * @param uploadInfo
     * @returns
     */
    const getUploadFileNameHtml = (uploadInfo: UploadOutput) => {
        return (
            <div class="uploadAndpreview--title-container">
                <div class="ffilepreview--item-icon">
                    <span class={['ffilepreview--filetype-icon', getFileTypeClassName(uploadInfo['file']?.name || '')]}></span>
                </div>
                <div class="uploadAndpreview--right">
                    <a class="item-content--title" title={uploadInfo['file']?.name}>
                        {uploadInfo['file']?.name || '无名称'}
                    </a>
                    <upload-progress
                        status={uploadInfo['type'] == 'done' ? 'success' : 'active'}
                        percent={getUploadProgress(uploadInfo)}
                        maxWidth={300}></upload-progress>
                </div>
            </div>
        );
    };
    /**
     * 返回预览文件的名称模版
     * @param previewInfo
     * @returns
     */
    const getPreviewFileNameHtml = (previewInfo: FUploadFileExtend) => {
        return (
            <div class="uploadAndpreview--title-container">
                <div class="ffilepreview--item-icon">
                    <span class={['ffilepreview--filetype-icon', getFileTypeClassName(previewInfo.name)]}></span>
                </div>
                <div class="uploadAndpreview--right">
                    <a
                        class={['item-content--title', "noPreview.value?'no-preview':''"]}
                        title={previewInfo.name}
                        onClick={(ev: MouseEvent) => filePreviewHandler(ev, previewInfo)}>
                        {previewInfo.name}
                    </a>
                </div>
            </div>
        );
    };
    /**
     * 返回文件大小的模版
     * @param state
     * @param fileInfo
     * @returns
     */
    const getFileSizeHtml = (state: string, uploadInfo: UploadOutput | null, previewInfo: FUploadFileExtend | null) => {
        return (
            <div class="uploadAndpreview--filesize-container">
                {state == 'preview' && previewInfo ? <span>{getRealFileSize(previewInfo.size)}</span> : null}
                {state == 'upload' && uploadInfo ? <span>{getUploadProgress(uploadInfo)}</span> : null}
            </div>
        );
    };
    /**
     * 返回附件上传的状态
     * @param state
     * @param fileInfo
     */
    const getFileStateHtml = (state: string, fileInfo: UploadOutput | null) => {
        return (
            <div class="uploadAndpreview--state-container">
                {state == 'upload' ? (
                    fileInfo && fileInfo.type != 'done' ? (
                        <p class="upload-state--uploading">
                            <i class="f-icon f-icon-clock text-warning"></i>
                            <span>正在上传...</span>
                        </p>
                    ) : (
                        <p class="upload-state--uploaded">
                            <i class="f-icon f-icon-success text-success"></i>
                            <span>上传成功</span>
                        </p>
                    )
                ) : state == 'preview' ? (
                    <p class="upload-state--uploaded">
                        <i class="f-icon f-icon-success text-success"></i>
                        <span>已上传</span>
                    </p>
                ) : (
                    ''
                )}
            </div>
        );
    };
    /**
     * 返回预览按钮模版
     * @param previewInfo
     * @returns
     */
    const getPreviewActionHtml = (previewInfo: FUploadFileExtend) => {
        return (
            <div class="uploadAndpreview--action-container">
                {!noDownload.value ? (
                    <button class="btn preview-btn" title="下载" onClick={(ev: MouseEvent) => fileDownloadHandler(ev, previewInfo)}>
                        <span class="f-icon f-icon-enclosure_download"></span>
                    </button>
                ) : (
                    ''
                )}
                {!noPreview.value ? (
                    <button class="btn preview-btn" title="预览" onClick={(ev: MouseEvent) => filePreviewHandler(ev, previewInfo)}>
                        <span class="f-icon f-icon-enclosure_browse"></span>
                    </button>
                ) : (
                    ''
                )}
                {editfile.value ? (
                    <button
                        class="btn preview-btn"
                        title={!canEditFile(previewInfo) ? '不能编辑' : '编辑'}
                        onClick={(ev: MouseEvent) => editFileHandler(ev, previewInfo)}
                        disabled={!canEditFile(previewInfo)}>
                        <span class="f-icon f-icon-edit" style="font-size: 12px"></span>
                    </button>
                ) : (
                    ''
                )}
                {!previewReadonly.value && !noDownload.value ? (
                    <button class="btn preview-btn" title="删除" onClick={(ev: MouseEvent) => fileRemoveHandler(ev, previewInfo)}>
                        <span class="f-icon f-icon-enclosure_delete" style="top: -1px"></span>
                    </button>
                ) : (
                    ''
                )}
            </div>
        );
    };
    /**
     * 下载
     * @param ev
     * @param fileInfo
     */
    const fileDownloadHandler = (ev: Event, fileInfo: FUploadFileExtend) => {
        ev.stopImmediatePropagation();
        ctx.emit('fileDownloadEvent', { fileInfos: [fileInfo], name: '' });
    };
    /**
     * 预览
     * @param ev
     * @param fileInfo
     */
    const filePreviewHandler = (ev: Event, fileInfo: FUploadFileExtend) => {
        ev.stopImmediatePropagation();
        if (noPreview.value) {
            return;
        }
        ctx.emit('filePreviewEvent', fileInfo);
    };

    const editFileHandler = (ev: Event, fileInfo: FUploadFileExtend) => {
        ev.stopImmediatePropagation();
        ctx.emit('editFileEvent', fileInfo);
    };

    /**
     * 删除数据
     * @param ev
     * @param fileInfo
     */
    const fileRemoveHandler = (ev: Event, fileInfo: FUploadFileExtend) => {
        //ev.stopImmediatePropagation();
        if (fileInfo.checked) {
            previewMultiSelected.value = previewMultiSelected.value.filter((n) => n.id !== fileInfo.id);
        }
        ctx.emit('fileRemoveEvent', fileInfo);
    };
    /**
     * 返回创建时间
     * @param previewInfo
     */
    const getPreviewDateHtml = (previewInfo: FUploadFileExtend) => {
        return <div class="uploadAndpreview--date-container">{previewInfo.createTime || ''}</div>;
    };

    /**
     * 判断是否显示checkbox
     */
    const judgeShowCheckbox = () => { };
    /**
     * 找到模版
     */
    const hasColumnHtmlFunc = (columnInfo: FUploadPreviewColumn, type = 'preview') => {
        let result = false;
        if (type == 'preview') {
            let previewDefaultFields = ['state', 'name', 'action', 'size', 'createTime'];
            return previewDefaultFields.findIndex((pfield) => pfield == columnInfo['field']) > -1 ? true : false;
        } else if (type == 'upload') {
            let uploadDefaultFields = ['state', 'name', 'size'];
            return uploadDefaultFields.findIndex((ufield) => ufield == columnInfo['field']) > -1 ? true : false;
        }
        return false;
    };

    /**
     * 找到模版
     */
    const findColumnHtmlFunc = (state: 'preview', uploadInfo: UploadOutput, previewInfo: any, columnInfo: FUploadPreviewColumn) => {
        let result = null;
        if (state == 'preview') {
            switch (columnInfo['field']) {
                case 'state':
                    result = getFileStateHtml('preview', null);
                    break;
                case 'name':
                    result = getPreviewFileNameHtml(previewInfo);
                    break;
                case 'action':
                    result = getPreviewActionHtml(previewInfo);
                    break;
                case 'size':
                    result = getFileSizeHtml(state, uploadInfo, previewInfo);
                    break;
                case 'createTime':
                    result = getPreviewDateHtml(previewInfo);
                    break;
                default:
                    result = '<div>' + previewInfo[columnInfo['field']] || '' + '</div>';
            }
        } else {
            switch (columnInfo['field']) {
                case 'state':
                    result = getFileStateHtml('upload', uploadInfo);
                    break;
                case 'name':
                    result = getUploadFileNameHtml(uploadInfo);
                    break;
                case 'size':
                    result = getFileSizeHtml(state, uploadInfo, previewInfo);
                    break;
                default:
                    result = '';
            }
        }
        return result;
    };
    /**
     * 是否显示预览状态列
     * @param columnInfo
     * @returns
     */
    const showPreviewStateColumn = (columnInfo: FUploadPreviewColumn) => {
        if (columnInfo['field'] == 'state' && (uploadDisabled.value || !uploadVisible.value || noDownload.value)) {
            return false;
        }
        return true;
    };

    /**
     * 批量下载附件
     * @param ev
     */
    const fileMultiDownloadHandler = (ev: Event) => {
        ev.stopImmediatePropagation();
        if (previewMultiSelectedLength.value > 1) {
            let rename = '';
            rename = getName(previewMultiSelected.value[0]['name']);
            ctx.emit('fileDownloadEvent', {
                fileInfos: previewMultiSelected.value,
                name: rename
            });
        }
    };

    /**
     * 获取名称
     * @param name
     * @returns
     */
    const getName = (name: string) => {
        if (name.lastIndexOf('.') > 0) {
            return name.substring(0, name.lastIndexOf('.'));
        }
        return '';
    };
    /**
     * 批量删除
     * @param ev
     */
    const multiFileRemoveHandler = (ev: Event) => {
        ev.stopImmediatePropagation();
        ctx.emit('fileRemoveEvent', previewMultiSelected.value);
    };

    /**
     * 选择或取消所有
     * @param ev
     */
    const selectOrCancelAllHandler = (ev: any) => {
        if (ev['checked']) {
            // 全选
            innerFileInfos.value.forEach((item) => {
                item.checked = true;
            });
            previewMultiSelected.value = [...innerFileInfos.value];
            previewSelectAllBtnChecked.value = true;
        } else {
            // 取消
            previewMultiSelected.value = [];
            innerFileInfos.value.forEach((item) => {
                item.checked = false;
            });
            previewSelectAllBtnChecked.value = false;
        }
        // 抛出多选
        ctx.emit('fPreviewMultiSelectedEvent', previewMultiSelected.value);
    };
    /**
     * 多选变更
     */
    const previewMultiSelectChangeHandler = (ev: any) => {
        let hasInArray = previewMultiSelected.value.findIndex((item) => item['id'] == ev['id']);
        let findInArray = innerFileInfos.value.findIndex((item) => item['id'] == ev['id']);
        if (findInArray > -1) {
            innerFileInfos.value[findInArray]['checked'] = ev['checked'];
        }

        if (ev['checked']) {
            //选入
            if (hasInArray == -1) {
                if (findInArray > -1) {
                    previewMultiSelected.value.push(innerFileInfos.value[findInArray]);
                }
            }
        } else {
            //移出
            if (hasInArray > -1) {
                previewMultiSelected.value.splice(hasInArray, 1);
            }
        }
        // 判断是否全选
        if (innerFileInfos.value.length > 0) {
            if (previewMultiSelected.value.length == innerFileInfos.value.length) {
                //都全选
                previewSelectAllBtnChecked.value = true;
            } else {
                // 未全选
                previewSelectAllBtnChecked.value = false;
            }
        }
        // 抛出多选
        ctx.emit('fPreviewMultiSelectedEvent', previewMultiSelected);
    };

    /**
     * allAddedToQueue 选中文件追加到队列
     * @param output
     */
    const uploadOutputHandler = (output: UploadOutput): void => {
        if (output.type === 'addedToQueue' && typeof output.file !== 'undefined') {
            uploadFiles.value.push({ type: output.type, file: output.file });
            // 开始上传
            startUpload(output.file);
        } else if (output.type === 'start') {
            // 开始上传
            updateFilesState(output, '');
        } else if (output.type == 'done') {
            // 上传完成
            updateFilesState(output, 'done');
            ctx.emit('fUploadDoneEvent', changeUploadFileToFileExtend(output.files));

            const newAddFiles = output.files.map((n) => {
                return {
                    checked: false,
                    id: n.id,
                    name: n.name,
                    size: n.size,
                    createTime: dateHlp.formatTo(new Date(), 'yyyy-MM-dd HH:mm:ss')
                };
            });
            innerFileInfos.value = [...newAddFiles, ...innerFileInfos.value];
            // 上传完成后不在当前页面上显示
            // hideAfterLoaded(output);
        } else if (output.type === 'cancelled' || output.type === 'removed' || output.type == 'error') {
            // 删除或者移除文件
            uploadFiles.value = uploadFiles.value.filter((fileOutput: UploadOutput) => {
                return output.files && output.files.findIndex((item) => fileOutput?.file?.id == item.id) < 0;
            });
            // 给出提示
            showNotify(output);
        } else if (output.type === 'rejected' && typeof output.file !== 'undefined') {
            // 上传被拒绝
            showNotify(output);
        }
    };
    /**
     * 处理上传信息
     * @param output
     */
    const showNotify = (output: UploadOutput) => {
        let notifyType = 'warning';
        if (output.type == 'cancelled' || output.type == 'removed') {
            notifyType = 'success';
        }
        let message = output.hasOwnProperty('message') ? output['message'] : '';
        // ----ToDo------- 提示不支持区分类型
        notifySer['show']({
            msg: message,
            timeout: 3000
        });
    };
    /**单个文件上传 */
    const startUpload = (file: UploadFile): void => {
        uploadInputEvent.next({ file: file, type: 'upload' });
    };
    /**
     * 更新附件的状态
     * @param output
     * @param eventType
     */
    const updateFilesState = (output: UploadOutput, eventType: string) => {
        let startFiles: UploadFile[] = [];
        if (output.files && output.files.length > 0) {
            // 此处更新界面可能有性能问题
            startFiles = output.files;
        } else if (typeof output.file !== 'undefined') {
            startFiles = [output.file];
        }
        eventType = eventType ? eventType : output.type;
        startFiles.map((item) => {
            const index = uploadFiles.value.findIndex((fileOutput) => typeof item !== 'undefined' && fileOutput?.file?.id === item.id);
            // 变更状态
            if (index > -1) {
                uploadFiles.value[index] = { type: eventType, file: item };
            }
        });
    };
    /**
     * 调用服务中的方法
     * @param incomingFiles 
     */
    const handleFilesFromService = (incomingFiles: FileList) => {
        apiSer.handleFiles(incomingFiles);
    }

    /**
     * 实例被卸载
     */
    onUnmounted(()=>{
        apiSer.destroyed();
    });

    return {
        uploadSelectText,
        disabled,
        uploadVisible,
        uploadDisabled,
        noDownload,
        previewVisible,
        previewReadonly,
        previewColumns,
        uploadFiles,
        innerFileInfos,
        previewEnableMulti,
        previewMultiSelectedLength,
        previewSelectAllBtnChecked,
        uploadEnableMulti,
        uploadInputOpts,
        multiFileRemoveHandler,
        previewMultiSelectChangeHandler,
        fileMultiDownloadHandler,
        selectOrCancelAllHandler,
        beforeUploadSupportInfoHtml,
        hasColumnHtmlFunc,
        findColumnHtmlFunc,
        showPreviewStateColumn,
        handleFilesFromService
    };
};
